﻿using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
using UnityEngine.UI;

namespace HBFramework
{
    /// <summary>
    /// Panel管理类
    /// </summary>
    public partial class PanelManager : Singleton<PanelManager>, ISingleton, ISingletonUpdate
    {
        public Vector2 resolution = new(1920, 1080); //分辨率
        private Transform root_panel; //根节点
        private readonly int layer_ui = 5; //UI

        int ISingletonUpdate.Order => SingletonOrder.First;

        void ISingleton.OnInit()
        {
            GameObject go = new GameObject("PanelRoot");
            GameObject.DontDestroyOnLoad(go);
            root_panel = go.transform;
            go.layer = layer_ui;
        }

        void ISingletonUpdate.OnUpdate()
        {
            //回收列表刷新
            if (recycleList != null)
            {
                for (int i = 0; i < recycleList.Count; i++)
                {
                    var recycle = recycleList[i].Refresh();
                    if (recycle)
                    {
                        recycleList.RemoveAt(i);
                        i--;
                    }
                }
            }

            //列表刷新
            if (panelList != null)
            {
                for (int i = 0; i < panelList.Count; i++)
                {
                    panelList[i].basePanel.OnUpdate();
                }
            }
        }

        void ISingleton.OnDestroy()
        {
        }
    }

    public partial class PanelManager
    {
        private List<PanelInfo> panelList;
        private List<PanelInfo> recycleList;

        /// <summary>
        /// 打开UI
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async UniTask<T> OpenPanel<T>() where T : BasePanel, new()
        {
            //回收UI
            if (recycleList != null)
            {
                for (int i = 0; i < recycleList.Count; i++)
                {
                    if (recycleList[i].basePanel is T)
                    {
                        var oldPanelInfo = recycleList[i];
                        oldPanelInfo.Show();
                        recycleList.RemoveAt(i);
                        panelList.Add(oldPanelInfo);
                        return oldPanelInfo.basePanel as T;
                    }
                }
            }

            //新建UI
            T newUI = new T();
            var uiPrefab = await AssetManagerProxy.Instance.LoadAsset<GameObject>(newUI.Path);
            var canvas = CreateCanvas(typeof(T).Name);
            canvas.sortingOrder = newUI.Layer;

            var uiGo = GameObject.Instantiate(uiPrefab, canvas.transform);
            PanelInfo uiInfo = new PanelInfo(newUI, canvas, uiGo);
            newUI.OnInit(uiGo);
            newUI.OnShow();
            panelList ??= new List<PanelInfo>();
            panelList.Add(uiInfo);
            return newUI;
        }

        /// <summary>
        /// 创建画布
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private Canvas CreateCanvas(string name)
        {
            GameObject go = new GameObject($"Canvas_{name}");
            go.transform.SetParent(root_panel);
            go.transform.localPosition = Vector3.zero;
            go.layer = layer_ui;

            Canvas canvas = go.AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceCamera;
            canvas.worldCamera = GameManagerProxy.Instance.UICamera;

            var scaler = go.AddComponent<CanvasScaler>();
            scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
            scaler.referenceResolution = resolution;
            scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
            scaler.matchWidthOrHeight = 0;
            go.AddComponent<GraphicRaycaster>();
            return canvas;
        }

        /// <summary>
        /// 关闭UI
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void ClosePanel<T>() where T : BasePanel, new()
        {
            var panelInfo = GetPanelInfo<T>();
            if (panelInfo == null)
            {
                DebugUtility.LogWarning("PanelManager", "panelInfo is null");
                return;
            }

            if (panelInfo.basePanel.RemainTime == 0)
            {
                panelInfo.Destroy();
                panelList.Remove(panelInfo);
            }
            else
            {
                panelInfo.Hide();
                panelList.Remove(panelInfo);
                recycleList ??= new List<PanelInfo>();
                recycleList.Add(panelInfo);
            }
        }

        /// <summary>
        /// 关闭UI
        /// </summary>
        /// <param name="panel"></param>
        public void ClosePanel(BasePanel panel)
        {
            var panelInfo = GetPanelInfo(panel);
            if (panelInfo == null)
            {
                DebugUtility.LogWarning("PanelManager", "panel is null");
                return;
            }

            if (panelInfo.basePanel.RemainTime > 0)
            {
                panelInfo.Hide();
                panelList.Remove(panelInfo);
                recycleList ??= new List<PanelInfo>();
                recycleList.Add(panelInfo);
            }
            else if (panelInfo.basePanel.RemainTime == -1)
            {
                panelInfo.Hide();
            }
            else
            {
                panelInfo.Destroy();
                panelList.Remove(panelInfo);
            }
        }

        /// <summary>
        /// 获取Panel
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetPanel<T>() where T : BasePanel, new()
        {
            var panelInfo = GetPanelInfo<T>();
            return panelInfo.basePanel as T;
        }

        /// <summary>
        /// 获取PanelInfo
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private PanelInfo GetPanelInfo<T>() where T : BasePanel, new()
        {
            for (int i = 0; i < panelList.Count; i++)
            {
                var kv = panelList[i];
                if (kv.basePanel is T)
                {
                    return kv;
                }
            }

            return null;
        }

        /// <summary>
        /// 获取PanelInfo
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private PanelInfo GetPanelInfo(BasePanel panel)
        {
            for (int i = 0; i < panelList.Count; i++)
            {
                var kv = panelList[i];
                if (kv.basePanel == panel)
                {
                    return kv;
                }
            }

            return null;
        }

        /// <summary>
        /// 显示UI
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void ShowPanel<T>() where T : BasePanel, new()
        {
            var panelInfo = GetPanelInfo<T>();
            if (panelInfo == null)
            {
                DebugUtility.LogWarning("PanelManager", "panel is null");
                return;
            }

            panelInfo.canvas.enabled = true;
        }

        /// <summary>
        /// 显示UI
        /// </summary>
        /// <param name="panel"></param>
        public void ShowPanel(BasePanel panel)
        {
            var panelInfo = GetPanelInfo(panel);
            if (panelInfo == null)
            {
                DebugUtility.LogWarning("PanelManager", "panel is null");
                return;
            }

            panelInfo.canvas.enabled = true;
        }

        /// <summary>
        /// 隐藏UI
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void HidePanel<T>() where T : BasePanel, new()
        {
            var panelInfo = GetPanelInfo<T>();
            if (panelInfo == null)
            {
                DebugUtility.LogWarning("PanelManager", "panel is null");
                return;
            }

            panelInfo.canvas.enabled = false;
        }

        /// <summary>
        /// 隐藏UI
        /// </summary>
        /// <param name="panel"></param>
        public void HidePanel(BasePanel panel)
        {
            var panelInfo = GetPanelInfo(panel);
            if (panelInfo == null)
            {
                DebugUtility.LogWarning("PanelManager", "panel is null");
                return;
            }

            panelInfo.canvas.enabled = false;
        }
    }
}